#include "pthreadPool.h"
#include "workCmd.h"

int doCd(char *dirName, int netFd, int userId);
int doLs(char *dirName, int netFd, int userId);
int doPwd(char *dirName, int netFd, int userId);
int doRm(char *dirName, int netFd, int userId);
int doMkdir(char *dirName, int netFd, int userId);

int handleShortCmd(trainState_t trainState, int netFd, int userId){
    //写入日志
    sysadd(userId, trainState.buf);

    char fileName[100] = {0};
    int i = trainState.preLength;
    while(trainState.buf[i] == ' '){
        ++i;
    }
    strcpy(fileName, trainState.buf + i);

    //分析命令
    if (strncmp("cd", trainState.buf, 2) == 0){
        doCd(fileName, netFd, userId);
    }
    else if (strncmp("ls", trainState.buf, 2) == 0){
        doLs(fileName, netFd, userId);
    }
    else if (strncmp("pwd", trainState.buf, 3) == 0){
        doPwd(fileName, userId, netFd);
    }
    else if (strncmp("rm", trainState.buf, 2) == 0){
        doRm(fileName, userId, netFd);
    }
    else if (strncmp("mkdir", trainState.buf, 5) == 0){
        doMkdir(fileName, netFd, userId);
    }

    return 0;
}

int doCd(char *dirName, int netFd, int userId){
    // 不考虑目标目录地址以/开头，这种情况直接报错
    // 写不动啦啊啦啦啦啦啦啦啦20250722
    int check = 0;
    if(dirName[0] == '/'){
        check = 1;
        send(netFd, &check, sizeof(check), MSG_NOSIGNAL);
        return 0;
    }
    int code = 0;
    int parentCode;
    getUserCode(userId, &code);// 获得本用户的当前目录编号
    parentCode = code;
    char pwd[1024] = {0};
    getUserPwd(userId, pwd);
    char *words[20] = {0};
    int i = 0;
    char s[100] = {0};
    // 如果是..就返回上级目录
    if(strcmp(dirName, "..") == 0 || strcmp(dirName, "../") == 0){
        if(code == 0){
            // 已经在根目录，不能返回上级
            check = 1;
            send(netFd, &check, sizeof(check), MSG_NOSIGNAL);
            return 0;
        }
        getParentId(code, &parentCode);
        code = parentCode;

        // 切分当前路径
        strcpy(s, pwd);
        words[i] = strtok(s, "/");
        ++i;
        while ((words[i] = strtok(NULL, "/")) != NULL){
            ++i;
        }
        bzero(pwd, sizeof(pwd));
        for(int j = 0; j < i - 1; ++j){
            strcat(pwd, words[j]);
            strcat(pwd, "/");
        }
    }
    else if(strcmp(dirName, "~/") == 0 || strcmp(dirName, "~") == 0){
        //回到根目录
        strcpy(pwd, "~/");
        code = 0;
    }
    // 不是..就去往目的地址
    else
    {
        // 将目标地址切分
        bzero(s, sizeof(s));
        bzero(words, sizeof(words));
        strcpy(s, dirName);
        words[i] = strtok(s, "/");
        ++i;
        while ((words[i] = strtok(NULL, "/")) != NULL){
            ++i;
        }
        for (int j = 0; j < i; ++j){
            if (strcmp(words[j], ".") == 0){
                continue;
            }
            if (strcmp(words[j], "~") == 0){
                parentCode = code = 0;
                continue;
            }
            if (strcmp(words[j], "..") == 0){
                if (code == 0){
                    // 已经在根目录，不能返回上级
                    check = 1;
                    send(netFd, &check, sizeof(check), MSG_NOSIGNAL);
                    return 0;
                }
                getParentId(code, &parentCode);
                code = parentCode;
                continue;
            }
            printf("%s\n", words[j]);
            char type[2];
            // 获取当前文件在虚拟文件目录的id和类型
            int ret = getFileCode(userId, words[j], &code, parentCode, type); 
            if (ret != 0 || strcmp(type, "d") != 0){
                // 文件查找失败；不是目录文件；不在可搜索路径下
                check = 1;
                send(netFd, &check, sizeof(check), MSG_NOSIGNAL);
                return 0;
            }
            if (parentCode != 0)
            {
                strcat(pwd, "/");
            }
            strcat(pwd, words[j]);
            parentCode = code; // 继续往下遍历
        }
    }
    // printf("pwd = %s, code = %d\n", pwd, code);
    updateUserPwd(userId, pwd, code);
    send(netFd, &check, sizeof(check), MSG_NOSIGNAL);
    train_t train;
    bzero(&train,sizeof(train));
    train.length = strlen(pwd);
    strcpy(train.data, pwd);
    send(netFd, &train, sizeof(train.length) + train.length, MSG_NOSIGNAL);
    return 0;
}

int doLs(char *fileName, int netFd, int userId){
    puts("ls");
    // 查看当前目录
    // printf("fileName lth = %ld\n", strlen(fileName));
    int code;
    int parentCode;
    int check = 0;
    char type[2];
    getUserCode(userId, &code);// 获得当前所在目录的id
    parentCode = code;
    if(fileName[0] == '/'){
        check = 1;
        send(netFd, &check, sizeof(check), MSG_NOSIGNAL);
        return 0;
    }
    if(strlen(fileName) == 0 || strcmp(fileName, ".") == 0 || strcmp(fileName, "./") == 0){
        // code不用改变
        printf("local!\n");
    }
    else{
        // 与cd一样的判断
        char pwd[1024] = {0};
        getUserPwd(userId, pwd);
        char *words[20] = {0};
        int i = 0;
        char s[100] = {0};
        // 是..的情况
        if (strcmp(fileName, "..") == 0 || strcmp(fileName, "../") == 0){
            if (code == 0){
                // 已经在根目录，不能返回上级
                check = 1;
                send(netFd, &check, sizeof(check), MSG_NOSIGNAL);
                return 0;
            }
            getParentId(code, &parentCode);
            code = parentCode;
        }
        // 不是..就去往目的地址
        else{
            // 将目标地址切分
            bzero(s, sizeof(s));
            bzero(words, sizeof(words));
            strcpy(s, fileName);
            words[i] = strtok(s, "/");
            ++i;
            while ((words[i] = strtok(NULL, "/")) != NULL){
                ++i;
            }
            for (int j = 0; j < i; ++j){
                if (strcmp(words[j], ".") == 0){
                    continue;
                }
                if (strcmp(words[j], "~") == 0){
                    // 如果以根目录开始，则改变code值为0
                    parentCode = code = 0;
                    continue;
                }
                if (strcmp(words[j], "..") == 0){
                    if (code == 0){
                        // 已经在根目录，不能返回上级
                        check = 1;
                        send(netFd, &check, sizeof(check), MSG_NOSIGNAL);
                        return 0;
                    }
                    getParentId(code, &parentCode);
                    code = parentCode;
                    continue;
                }
                // printf("%s\n", words[j]);
                char type[2];
                int ret = getFileCode(userId, words[j], &code, parentCode, type); // 获取当前文件在虚拟文件目录的id和类型
                if (ret != 0 || strcmp(type, "d") != 0)  // 文件查找失败；不是目录文件；不在可搜索路径下
                {
                    check = 1;
                    send(netFd, &check, sizeof(check), MSG_NOSIGNAL);
                    return 0;
                }
                parentCode = code; // 继续往下遍历，遍历结束code就是要浏览的目录的文件id
            }
        }
    }
    printf("code = %d\n", code);
    send(netFd, &check, sizeof(check), MSG_NOSIGNAL);
    findCodeFiles(netFd, code, userId);// 把找到的文件发给客户端
}

int doPwd(char *fileName, int userId, int netFd){
    puts("pwd");
    char pwd[1024] = {0};
    getUserPwd(userId, pwd);
    printf("pwd : %s\n", pwd);
    train_t train;
    bzero(&train,sizeof(train));
    train.length = strlen(pwd);
    strcpy(train.data, pwd);
    send(netFd, &train, sizeof(train.length) + train.length, MSG_NOSIGNAL);
    return 0;
}

int doRm(char *fileName, int userId, int netFd)
{
    puts("rm");
    int code;
    int parentCode;
    char type[2] = {0};
    char file[100] = {0};
    int check = 0;
    getUserCode(userId, &code);// 获得当前所在目录的id
    parentCode = code;
    if(fileName[0] == '/' || strcmp(fileName, ".") == 0 || strcmp(fileName, "~/") == 0 || strcmp(fileName, "./") == 0 || strcmp(fileName, "..") == 0 || strcmp(fileName, "../") == 0){
        check = 1;
        send(netFd, &check, sizeof(check), MSG_NOSIGNAL);
        return 0;
    }
    else{
        // 不是以上几种情况就遍历获得要删除的文件的id和类型
        // 将目标地址切分
        char *words[20] = {0};
        int i = 0;
        char s[100] = {0};
        strcpy(s, fileName);
        words[i] = strtok(s, "/");
        ++i;
        while ((words[i] = strtok(NULL, "/")) != NULL){
            ++i;
        }

        for (int j = 0; j < i; ++j)
        {
            if (strcmp(words[j], ".") == 0){
                continue;
            }
            if (strcmp(words[j], "~") == 0){
                parentCode = code = 0;
                continue;
            }
            if (strcmp(words[j], "..") == 0){
                if (code == 0){ 
                    // 已经在根目录，不能返回上级
                    check = 1;
                    send(netFd, &check, sizeof(check), MSG_NOSIGNAL);
                    return 0;
                }
                getParentId(code, &parentCode);
                code = parentCode;
                continue;
            }
            // printf("%s\n", words[j]);

            int ret = getFileCode(userId, words[j], &code, parentCode, type); // 获取当前文件在虚拟文件目录的id和类型
            printf("ret = %d\n", ret);
            if(ret != 0){
                // 路径错误
                check = 1;
                send(netFd, &check, sizeof(check), MSG_NOSIGNAL);
                return 0;
            }
            if(j != i-1){
                parentCode = code; // 继续往下遍历，遍历结束code就是要浏览的目录的文件id
            }
        }
        strcpy(file, words[i - 1]);
    }
    if(code == 0){
        check = 1;
        send(netFd, &check, sizeof(check), MSG_NOSIGNAL);
        return 0;
    }
    // printf("code = %d\n", code);
    if(strcmp(type, "f") == 0){
        char md5Str[MD5_STR_LEN + 1] = {0};
        getVirtualFileMd5(file, userId, parentCode, md5Str);// 要先查询再删除
        minusLink(md5Str);// 本地链接数减一
    }
    delVirtualFile(code, userId);// 先查询后删除
    send(netFd, &check, sizeof(check), MSG_NOSIGNAL);
}

int doMkdir(char *dirName, int netFd, int userId)
{
    puts("mkdir");
    int check = 0;
    int code;
    getUserCode(userId, &code);
    // printf("code = %d\n", code);
    int test = 0;
    char type[2] = {0};
    int ret = getFileCode(userId, dirName, &test, code, type);
    if(ret == 0){
        // 说明该名称的文件夹已经存在
        check = 1;
        send(netFd, &check, sizeof(check), MSG_NOSIGNAL);
        return 0;
    }
    check = addVirtualDir(code, dirName, userId);
    send(netFd, &check, sizeof(check), MSG_NOSIGNAL);
    return 0;
}


